package com.fitc.json;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.Type;
import java.net.URL;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import java.util.Set;

import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonStreamParser;
import com.google.gson.reflect.TypeToken;

public class Reader {

	/**
	 * @param args
	 * @throws IOException
	 */
	Set<Photo> photos = new HashSet<Photo>();
	static Calendar day;

	private int jsonProcessor(URL myUrl) throws IOException {
		Set<Photo> myPhotos = new HashSet<Photo>(500);
		Gson gson = new Gson();

		BufferedReader in = new BufferedReader(new InputStreamReader(
				myUrl.openStream()));

		JsonStreamParser jsp = new JsonStreamParser(in);
		JsonObject jo1 = jsp.next().getAsJsonObject();
		JsonElement je = jo1.get("photos");

		if (je != null) {
			JsonObject jo2 = je.getAsJsonObject();
			JsonArray ja = jo2.getAsJsonArray("photo");

			// System.out.println(ja.size());
			Iterator<JsonElement> iterator = ja.iterator();

			while (iterator.hasNext()) {
				JsonElement json2 = (JsonElement) iterator.next();
				Photo p = gson.fromJson(json2, Photo.class);
				myPhotos.add(p);
			}

			if (myPhotos.size() > 0) {
				// add to overall set
				System.out.print("size before: " + photos.size() + "   ");
				photos.addAll(myPhotos);
				System.out.println("after: " + photos.size() + "   ");
				return myPhotos.size();
			} else {
				return 0;
			}
		}

		return -1;
	}

	private static final String FLICKR_URL = "http://api.flickr.com/services/rest/?method=flickr.interestingness.getList&per_page=500&api_key=685f89b75efe5c17eac8e4ecb90ff4f2&format=json&nojsoncallback=1&extras=url_q,tags,path_alias";

	private static final String EXPORT_FILE = "export.txt";

	public boolean execute() throws IOException {
		URL url;
		// If start date has not been set
		if (START_DATE == null) {
			START_DATE=null;
			// get todays photos
			if (!HAVE_TODAYS) {
				url = new URL(FLICKR_URL);
				jsonProcessor(url);
				HAVE_TODAYS = true;
				this.days_done++;
				total_days_done++;
			}
			// Ignore duff last day that seems to return no result
			day = Calendar.getInstance();
			day.add(Calendar.DAY_OF_YEAR, -total_days_done);
		} else {

		}

		// get photos for previous days
		do {

			if (total_days_done >= TOTAL_NUMBER_OF_DAYS)
				return true;

			day.add(Calendar.DAY_OF_YEAR, -1);
			String formattedDate = getFormattedDate(day);
			System.out.println(formattedDate);

			url = new URL(FLICKR_URL + "&date=" + formattedDate);
			System.out.println(url);

			int n = jsonProcessor(url); // will be negative if null from json
										// parse

			if (n >= 0) {
				this.days_done++;
				total_days_done++;
			}
		} while (this.days_done < DAYS_AT_A_TIME);

		System.out.println("DONE. Size:" + photos.size());
		return false;
	}

	public Set<Photo> getPhotos() {
		return photos;
	}

	public Photo getRandomPhoto() {
		int size = photos.size();
		int item = new Random().nextInt(size); // In real life, the Random
												// object should be rather more
												// shared than this
		int i = 0;
		for (Photo p : photos) {
			if (i == item)
				return p;
			i = i + 1;
		}
		return null;

	}

	public void exportToTxt() {
		BufferedWriter f;
		Iterator<Photo> iterator = photos.iterator();

		try {
			f = new BufferedWriter(new FileWriter(EXPORT_FILE));

			while (iterator.hasNext()) {
				Photo p = (Photo) iterator.next();
				f.write(p.toString());
				f.newLine();
			}
			f.flush();
			f.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	private static int TOTAL_NUMBER_OF_DAYS;
	private static int DAYS_AT_A_TIME;
	private static boolean HAVE_TODAYS = false;
	private static Date START_DATE = null;

	private static int total_days_done = 0;
	private int days_done = 0;

	public static void setTotalNumberOfDays(int numberOfDays) {
		TOTAL_NUMBER_OF_DAYS = numberOfDays;
	}

	public static void setDaysAtATime(int daysAtATime) {
		DAYS_AT_A_TIME = daysAtATime;
	}

	public static void setDayToStart(String strDate) {
		DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
		try {
			START_DATE = df.parse(strDate);
			day = DateToCalendar(START_DATE);
			day.add(Calendar.DAY_OF_YEAR, +1);
		} catch (ParseException e) {
			// TODO Auto-generated catch block
			START_DATE = null;
		}
	}

	public String getNextDate() {
		Calendar dayBefore = (Calendar) day.clone();
		dayBefore.add(Calendar.DAY_OF_YEAR, -1);
		return getFormattedDate(dayBefore);
	}

	private String getFormattedDate(Calendar c) {
		Date oneDayBefore = c.getTime();
		DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
		return df.format(oneDayBefore);
	}

	public static Calendar DateToCalendar(Date date) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		return cal;
	}

}
